package com.kylin.common.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.kylin.common.core.entity.DataEntity;
import com.kylin.common.core.entity.Page;
import com.kylin.common.core.mapper.DataMapper;
import com.kylin.common.core.service.DataService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.binding.MapperMethod;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 通用增删改查服务接口实现
 *
 * @author wuhao
 * @version 1.0 - 2019-06-04
 */
public abstract class DataServiceImpl<M extends DataMapper<T>, T extends DataEntity<?>> extends BaseServiceImpl<M, T> implements DataService<T> {

    /**
     * 根据ID查询对象
     * @param id 主键ID
     * @return
     * @version 1.0  by wuhao at 2019-03-12
     */
    @Override
    public T getById(Serializable id){
        T item = this.mapper.selectById(id);
        // 设置缓存
        if(item != null) {
            this.setCache(Arrays.asList(item));
        }
        return item;
    }

    /**
     * 获取单个对象
     *
     * @param entity 实体对象T
     * @return
     * @version 1.0  by wuhao at 2019-03-12
     */
    @Override
    public T get(T entity) {
        QueryWrapper<T> queryWrapper = getQueryWrapper(entity);
        T item =  this.mapper.selectOne(queryWrapper);

        // 设置缓存
        if(item != null) {
            this.setCache(Arrays.asList(item));
        }

        return item;
    }

    /**
     * 根据条件获取list结果
     *s
     * @param entity 实体对象
     * @return
     * @version 1.0  by wuhao at 2019-03-12
     */
    @Override
    public List<T> list(T entity) {
        QueryWrapper<T> queryWrapper = getQueryWrapper(entity);
        // 加上sql过滤
        queryWrapper.apply(StringUtils.isNotBlank(entity.getSqlFilter()),entity.getSqlFilter());

        List<T> list = this.mapper.selectList(queryWrapper);

        // 设置缓存数据
        this.setCache(list);

        return list;
    }

    /**
     * 分页查询
     * queryWapper不为空，优先选择queryWapper作为查询条件
     *
     * @param page   分页
     * @param entity 查询条件实体对象
     * @return
     * @version 1.0  by wuhao at 2019-03-12
     */
    @Override
    public Page<T> listPage(Page<T> page, T entity) {
        QueryWrapper<T> queryWrapper = getQueryWrapper(entity);
        // 加上sql过滤
        queryWrapper.apply(StringUtils.isNotBlank(entity.getSqlFilter()),entity.getSqlFilter());

        return this.mapper.selectPage(page,queryWrapper);
    }

    /**
     * 新增数据
     *
     * @param entity 实体对象
     * @return
     * @version 1.0  by wuhao at 2019-03-12
     */
    @Override
    public int insert(T entity) {
        int count = this.mapper.insert(entity);
        // 清除缓存信息
        this.clearCache();
        return count;
    }

    /**
     * 更新数据
     *
     * @param entity 实体对象
     * @return
     * @version 1.0  by wuhao at 2019-03-12
     */
    @Override
    public int update(T entity) {
        int count = this.mapper.updateById(entity);
        // 清除缓存信息
        this.clearCache();
        return count;
    }

    /**
     * 保存数据
     * 如果数据库没有就新增，有则更新
     *
     * @param entity
     * @return
     * @version 1.0  by wuhao at 2019-03-12
     */
    @Override
    public int save(T entity) {
        if(ObjectUtils.isEmpty(entity.getId())){
            entity.perInsert();
            return insert(entity);
        }else{
            entity.perUpdate();
            return update(entity);
        }
    }

    /**
     * 删除数据
     *
     * @param id 编号ID
     * @return
     * @version 1.0  by wuhao at 2019-03-12
     */
    @Override
    public int delete(Serializable id) {
        int count = this.mapper.deleteById(id);
        // 清除缓存信息
        this.clearCache();
        return count;
    }

    /**
     * 更新状态
     * @param id 实体类 id，
     * @param status 状态
     * @return
     * @version 1.0  by wuhao at 2020/9/1
     */
    @Override
    public int updateStatus(Long id, String status){
        com.kylin.common.core.validator.Assert.isBlank("缺少编号或状态值", id, status);
        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("status", status)
                .eq("id", id);

        int count = this.mapper.update(null, updateWrapper);
        // 清除缓存信息
        this.clearCache();
        return count;
    }

    /**
     * 根据 columnMap 条件，删除记录
     * @param columnMap 表字段 map 对象
     * @return
     * @since  2.2.5  by wuhao at 2021/9/1
     */
    @Override
    public int removeByMap(Map<String, Object> columnMap) {
        com.baomidou.mybatisplus.core.toolkit.Assert.notEmpty(columnMap, "error: columnMap must not be empty");

        int count = this.mapper.deleteByMap(columnMap);
        // 清除缓存信息
        this.clearCache();
        return count;
    }


    /**
     * 批量新增数据
     * @param entityList 数据列表
     * @return
     * @version 1.0  by wuhao at 2019/8/26
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertBatch(Collection<T> entityList){
        int count =  insertBatch(entityList,entityList.size());
        // 清除缓存信息
        this.clearCache();
        return count;
    }

    /**
     * 批量新增数据
     * @param entityList 数据列表
     * @param batchSize 每次批量新增的数据量
     * @return
     * @version 1.0  by wuhao at 2019/8/26
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertBatch(Collection<T> entityList, int batchSize){
        String sqlStatement = getSqlStatement(SqlMethod.INSERT_ONE);
        boolean isSuccess = executeBatch(entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity));
        if(isSuccess) {
            // 清除缓存信息
            this.clearCache();
            return entityList.size();
        } else {
            return 0;
        }
    }

    /**
     * 根据ID 批量更新
     * @param entityList 更新列表
     * @return
     * @version 1.0  by wuhao at 2020-06-26
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateBatchById(Collection<T> entityList){
        int count = updateBatchById(entityList, entityList.size());
        // 清除缓存信息
        this.clearCache();
        return count;
    }

    /**
     * 根据ID 批量更新
     * @param entityList 更新列表
     * @param batchSize  每次更新数量
     * @return
     * @version 1.0  by wuhao at 2020-06-26
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateBatchById(Collection<T> entityList, int batchSize) {
        Assert.notEmpty(entityList, "error: entityList must not be empty");
        String sqlStatement = getSqlStatement(SqlMethod.UPDATE_BY_ID);
        boolean isSuccess = executeBatch(entityList, batchSize, (sqlSession, entity) -> {
            MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
            param.put(Constants.ENTITY, entity);
            sqlSession.update(sqlStatement, param);
        });
        if(isSuccess) {
            // 清除缓存信息
            this.clearCache();
            return entityList.size();
        } else {
            return 0;
        }
    }

    /**
     * 批量删除数据
     * @param ids 需要删除的ID列表
     * @return
     * @version 1.0  by wuhao at 2019-03-26
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteBatchIds(List<Serializable> ids){
        // 清除缓存信息
        this.clearCache();
        return this.mapper.deleteBatchIds(ids);
    }

    /**
     * 设置缓存，此方法一般用于系统不怎么变化的数据
     * 目前作用于： list, get, getById
     * @version 1.0  by wuhao at 2020-12-28
     */
    protected void setCache(List<T> list) {

    }

    /**
     * 清除缓存，此方法一般用于系统不怎么变化的数据
     * 目前作用于： save， insert， update， delete
     * @version 1.0  by wuhao at 2020-12-28
     */
    protected void clearCache() {

    }

    /** 构建通用查询条件 */
    private QueryWrapper<T> getQueryWrapper(T entity) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        // 无查询条件时，将对象放入查询对象中，方便快速查询
        if(entity.getQueryWrapper().isEmptyOfWhere()){
            queryWrapper.setEntity(entity);
        } else {
            queryWrapper = (QueryWrapper<T>) entity.getQueryWrapper();
        }
        return queryWrapper;
    }
}
